// -------------------------------------------------
// BlinKit - BlinKit Library
// -------------------------------------------------
//   File Name: dom_timer_coordinator.cpp
// Description: DOMTimerCoordinator Class
//      Author: Ziming Li
//     Created: 2021-07-23
// -------------------------------------------------
// Copyright (C) 2021 MingYang Software Technology.
// -------------------------------------------------

// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "./dom_timer_coordinator.h"

#include <algorithm>
#include "blinkit/blink/renderer/core/dom/ExecutionContext.h"
#include "blinkit/blink/renderer/core/frame/dom_timer.h"

namespace blink {

DOMTimerCoordinator::DOMTimerCoordinator(const std::shared_ptr<WebTaskRunner> &timerTaskRunner)
    : m_circularSequentialID(0)
    , m_timerNestingLevel(0)
    , m_timerTaskRunner(timerTaskRunner)
{
}

int DOMTimerCoordinator::installNewTimeout(ExecutionContext* context, std::unique_ptr<ScheduledAction> &action, int timeout, bool singleShot)
{
    // FIXME: DOMTimers depends heavily on ExecutionContext. Decouple them.
    ASSERT(context->timers() == this);
    int timeoutID = nextID();

    GCRefPtr<DOMTimer> timer = DOMTimer::create(context, action, timeout, singleShot, timeoutID);
    m_timers.emplace(timeoutID, timer);

    timer->suspendIfNeeded();

    return timeoutID;
}

void DOMTimerCoordinator::removeTimeoutByID(int timeoutID)
{
    if (timeoutID <= 0)
        return;

    auto it = m_timers.find(timeoutID);
    if (m_timers.end() != it)
    {
        it->second->disposeTimer();

        m_timers.erase(it);
    }
}

DEFINE_TRACE(DOMTimerCoordinator)
{
#if ENABLE(OILPAN)
    visitor->trace(m_timers);
#endif
}

int DOMTimerCoordinator::nextID()
{
    while (true) {
        ++m_circularSequentialID;

        if (m_circularSequentialID <= 0)
            m_circularSequentialID = 1;

        if (!zed::key_exists(m_timers, m_circularSequentialID))
            return m_circularSequentialID;
    }
}

void DOMTimerCoordinator::setTimerTaskRunner(const std::shared_ptr<WebTaskRunner> &timerTaskRunner)
{
    m_timerTaskRunner = timerTaskRunner;
}

} // namespace blink
